﻿require_relative "pde_headless_lib"
require "FileUtils"
require "find"
include PDEHeadlessUtil 

# PDE headless autobuild 类
# @author 许祯
class PDEHeadlessAutoBuild

	attr_accessor :m_build_info, :m_build_directory, :m_tag_dest_urls

	# @param [PDEHeadlessBuildInfo] build_info
	# @param [String] build_directory
	def initialize( build_info, build_directory )
		@m_build_info = build_info
		@m_build_directory = build_directory
		## map = { svn-info => tag_dest_url }
		@m_tag_dest_urls = {}
		@m_username = @m_build_info.m_global_setting.m_username
		@m_password = @m_build_info.m_global_setting.m_password
		@m_build_timestamp = @m_build_info.m_global_setting.m_build_timestamp
	end
	
	# build前的准备工作
	#* 自动创建tag
	#* 
	#*
	#* 
	def before_build
		auto_tag
		backup_and_new_build_directory
		export_from_tag
		remove_readonly_attribute
	end

	# build完成后的工作
	def after_build

	end

	@@Template_build_feature_command = "ant.bat -f ant_build_file.xml buildFeature -Dtimestamp=${timestamp} -Dbuildfeaturename=${feature_id} "

	# build所有feature
	def build_all
		commands = []
		@m_build_info.m_svn_infoes.each do |svn_info|
			svn_info.m_feature_IDs.each do |feature_id|	
				command = @@Template_build_feature_command
							.gsub(/\${timestamp}/,@m_build_timestamp)
							.gsub(/\${feature_id}/,feature_id)
				commands << command
			end
		end

		PDEHeadlessUtil.execute_commands(commands)
	end

	@@Constants_MANIFEST_Name = "MANIFEST.MF"

	# 调用系统命令，移除MANIFEST.MF文件的只读属性
	# pde headless build的时候，需要往MANIFEST.MF中写文件，如果文件是readonly的将会报错
	def remove_readonly_attribute
		manifest_file_list = []	
		Find.find(@m_build_directory) do |path|
			Find.prune if [".",".."].include? path
			case @@Constants_MANIFEST_Name
			when String
				manifest_file_list << path if File.basename(path) == @@Constants_MANIFEST_Name
			else
				raise ArgumentError
			end
		end
		
		commands = []
		manifest_file_list.each do |filepath|
			## FIXME only Windows works
			commands << "attrib -R #{filepath}"
		end
		
		PDEHeadlessUtil.execute_commands( commands )

	end
	
	# 将原始的buildDirectory目录重命名,并创建新的buildDirectory目录
	def backup_and_new_build_directory 
		#FileUtils.rm_rf @m_build_directory
		FileUtils.mv @m_build_directory, "#{@m_build_directory}_before_#{@m_build_timestamp}"
		FileUtils.mkdir @m_build_directory
	end

	@@Template_tag_name = "BL_${Timestamp}_${BuildType}_${Alias}"
	@@Template_tag_message = "auto tag from ${src_url} to ${dest_url} "
	@@Template_tag_command = "svn copy ${src_url} -r ${revision} ${dest_url}  --message=\"${message}\" --username=\"${username}\" --password=\"${password}\""
	
	# 自动创建tag
	def auto_tag
		commands = []
		@m_build_info.m_svn_infoes.each do |info|	
			base_url = info.m_url
			dest_url = get_tag_url(info)

			tag_message = @@Template_tag_message
							.gsub(/\${src_url}/,base_url)
							.gsub(/\${dest_url}/,dest_url)

			command = @@Template_tag_command
						.gsub(/\${src_url}/,base_url)
						.gsub(/\${dest_url}/,dest_url)
						.gsub(/\${revision}/,info.m_revision)
						.gsub(/\${message}/,tag_message)
						.gsub(/\${username}/,@m_username)
						.gsub(/\${password}/,@m_password)
			commands << command
			@m_tag_dest_urls[base_url] = dest_url
		end
		PDEHeadlessUtil.execute_commands( commands )
	end

	@@Template_export_command = "svn export ${tag_url}${target_dir}/${project_id} ${dest_path} --force"
	@@Template_dest_feature = "${build_directory}${target_dir}/${feature_id}"

	# 从自动创建的tag中export代码
	def export_from_tag 
		@m_build_info.m_svn_infoes.each do |info|	
			dir_features = info.m_dir_features
			dir_plugins = info.m_dir_plugins

			info.m_feature_IDs.each do |feature_id|
				dest_feature = @@Template_dest_feature
								.gsub(/\${build_directory}/,PDEHeadlessUtil.correct_path( @m_build_directory ))
								.gsub(/\${target_dir}/,"features")
								.gsub(/\${feature_id}/,feature_id)


				command = @@Template_export_command
							.gsub(/\${tag_url}/,PDEHeadlessUtil.correct_path(@m_tag_dest_urls[info.m_url] ))
							.gsub(/\${target_dir}/,dir_features)
							.gsub(/\${project_id}/,feature_id)
							.gsub(/\${dest_path}/,dest_feature)
				
				# export feature
				PDEHeadlessUtil.execute_command( command )

				# get all plugins required by the feature
				feature_file = File.new( "#{dest_feature}/feature.xml" )	

				required_plugins = get_feature_require_plugins( feature_file )
				
				commands = []
				required_plugins.each do |plugin|
					dest_plugin = @@Template_dest_feature
								.gsub(/\${build_directory}/,PDEHeadlessUtil.correct_path( @m_build_directory ))
								.gsub(/\${target_dir}/,"plugins")
								.gsub(/\${feature_id}/,plugin)
	
					command = @@Template_export_command
							.gsub(/\${tag_url}/,PDEHeadlessUtil.correct_path(@m_tag_dest_urls[info.m_url] ))
							.gsub(/\${target_dir}/, dir_plugins )
							.gsub(/\${project_id}/,plugin)
							.gsub(/\${dest_path}/,dest_plugin )
					
					commands << command
				end
				PDEHeadlessUtil.execute_commands( commands )
			end
		end
	end

	# 获取feature.xml文件中require的插件id
	# @param [File] feature_file 需要获取的feature.xml
	# @return [Array] result_plugin_ids，该feature_file包含的插件信息
	def get_feature_require_plugins( feature_file )
		build_directory = PDEHeadlessUtil.correct_path ( @m_build_directory ) 
		result_plugin_ids = []
		begin	
			feature_doc = Document.new(feature_file)
			feature_doc.elements.each("feature/plugin") do |element|
				plugin_id = element.attributes["id"].to_s
				result_plugin_ids << plugin_id
			end
		rescue Exception => e
			puts e
		end
		return result_plugin_ids 
	end


	@@URL_separate = ["trunk","branches"]
	
	# 生成tag的url
	# @param [PDEHeadlessBuildInfo::SVNInfo] svninfo
	# @return [String] svninfo的tag url
	# @raise url地址必须包含"trunk"或者"branches",如果没有包含，生成tag_url失败
	def get_tag_url( svn_info )
		url = svn_info.m_url

		tag_name = @@Template_tag_name
			.gsub(/\${Timestamp}/, @m_build_timestamp)
			.gsub(/\${BuildType}/, svn_info.m_build_type)
			.gsub(/\${Alias}/, svn_info.m_url_alias)

		seprate_index = nil
		@@URL_separate.each do |seprate|
			if url.index(seprate) != nil
				seprate_index = url.index(seprate)
				break
			end
		end
		raise "URL must contains one of #{@@URL_separate} " if seprate_index == nil
		result_tag_url = "#{url[0,seprate_index]}tags/#{tag_name}"

		return result_tag_url
	end
	
end

# 显示用法
def show_usage
	usage = '''
	USAGE:
	ruby pde_headless_autobuild.rb ARG1 ARG2
		ARG1 => build_input_file_path	
		ARG2 => build_directory_path
	'''
	puts usage
end

## execute this file
if __FILE__==$0

	puts "execute pde_headless_autobuild.rb"	
	
	if ARGV[0] == nil or ARGV[1] == nil 
		show_usage
		raise "ERROR INPUT"
	end

	__build_input_file_path = ARGV[0]
	__build_directory = ARGV[1]

	__build_info = PDEHeadlessBuildInfo.parse_input(__build_input_file_path)
	
	auto_build = PDEHeadlessAutoBuild.new __build_info, __build_directory

	auto_build.before_build
	auto_build.build_all
	auto_build.after_build

end

